import { RuntimeError } from '@ibiz-template/core';
import {
  ControlController,
  IDashboardState,
  IDashboardEvent,
  IDashboardController,
  IPortletProvider,
  IPortletController,
  IPortletContainerController,
  getPortletProvider,
  getOriginData,
} from '@ibiz-template/runtime';
import {
  IDashboard,
  IDBContainerPortletPart,
  IDBPortletPart,
} from '@ibiz/model-core';

/**
 * 数据看板部件控制器
 * @author lxm
 * @date 2023-07-07 03:27:29
 * @export
 * @class DashboardController
 * @extends {ControlController<IDashboard, IDashboardState, IDashboardEvent>}
 * @implements {IDashboardController}
 */
export class DashboardController
  extends ControlController<IDashboard, IDashboardState, IDashboardEvent>
  implements IDashboardController
{
  /**
   * 所有数据看板成员的适配器
   *
   * @author lxm
   * @date 2022-08-24 20:08:07
   * @type {{ [key: string]: IPortletProvider }}
   */
  providers: { [key: string]: IPortletProvider } = {};

  /**
   * 门户部件控制器
   *
   * @author lxm
   * @date 2022-10-20 22:10:26
   * @type {{ [key: string]: IPortletController }}
   */
  portlets: { [key: string]: IPortletController } = {};

  protected initState(): void {
    super.initState();
  }

  protected async onCreated(): Promise<void> {
    await super.onCreated();
    await this.initPortlets(this.model.controls!);

    // 实体门户视图监听视图数据变更，刷新界面行为组的状态。
    const { appDataEntityId } = this.view.model;
    if (appDataEntityId) {
      this.view.evt.on('onDataChange', event => {
        const data = getOriginData(event.data);
        if (data) {
          this.dataChangeNotify(data);
        }
      });
    }
  }

  /**
   * 初始化子门户部件
   *
   * @author lxm
   * @date 2022-10-21 03:10:49
   * @param {PortletPartModel[]} portletModels
   * @param {ContainerPortletController} [parent]
   * @returns {*}  {Promise<void>}
   */
  async initPortlets(
    portletModels: IDBPortletPart[],
    parent?: IPortletContainerController,
  ): Promise<void> {
    if (!portletModels?.length) {
      return;
    }
    await Promise.all(
      portletModels.map(async portlet => {
        const provider = await getPortletProvider(portlet);
        if (provider) {
          this.providers[portlet.id!] = provider;
          const controller = await provider.createController(
            portlet,
            this,
            parent,
          );
          this.portlets[portlet.id!] = controller;
          if ((portlet as IDBContainerPortletPart).controls?.length) {
            await this.initPortlets(
              (portlet as IDBContainerPortletPart).controls!,
              controller as IPortletContainerController,
            );
          }
        }
      }),
    );
  }

  /**
   * 通知所有表单成员表单操作过程中的数据变更
   *
   * @author lxm
   * @date 2022-09-20 18:09:40
   * @param {string[]} names
   */
  async dataChangeNotify(data: IData): Promise<void> {
    // 通知所有成员项去处理成员项相关逻辑
    const values = await Promise.allSettled(
      Object.values(this.portlets).map(async portlet => {
        return portlet.dataChangeNotify(data);
      }),
    );
    if (values.find(item => item.status === 'rejected')) {
      ibiz.log.error('dataChangeNotify报错', values);
      throw new RuntimeError('数据变更后有错误');
    }
  }
}
